/**
 * This software was produced for the U. S. Government
 * under Contract No. FA8721-09-C-0002, and is
 * subject to the Rights in Noncommercial Computer Software
 * and Noncommercial Computer Software Documentation Clause
 * (DFARS) 252.227-7014 (JUN 1995)
 * 
 * (c) 2009 The MITRE Corporation. All Rights Reserved.
 *
 * SPMIF to OPNET Translator
 * Author: ewalters
 * Created: 11:50:54 AM, Aug 3, 2007
 * MITRE Corporation
 */
package com.mitre.spmif2opnet.analysis;

import java.util.Collection;

import javax.xml.bind.JAXBException;

import com.mitre.spmif2opnet.XMLInterface;
import com.mitre.spmif2opnet.analysis.ast.Node;
import com.mitre.spmif2opnet.analysis.ast.Project;
import com.mitre.spmif2opnet.analysis.ast.Scenario;
import com.mitre.spmif2opnet.analysis.ast.Graph;
import com.mitre.spmif2opnet.spmif.ProjectType;

/**
 * Symbol representing reference to a single node
 */
public class LinkSymbol extends Symbol {
	/**
	 * The node we point to.
	 */
	private Node        _node;
	
	/** 
	 * Default constructor
	 * @param id our identifier
	 */
	public LinkSymbol(Identifier id) {
		super(id);
		_node = null;
	}
	
	/** 
	 * node accessor
	 * @return the node
	 */
	public Node getNode() {
		return _node;
	}
	
	/**
	 * node mutator
	 * @param n the node
	 */
	public void setNode(Node n) {
		_node = n;
	}
	
	/**
	 * Do we know what node we are pointing to?
	 */
	public boolean isResolved() {
		return (_node != null);
	}

	/**
	 * Resolve the symbol using the given analysis context
	 * Important info for a link: scenario file, scenario name, node name
	 * @param c the context
	 */
	public void resolve(AnalysisContext c) {
		if (this.isResolved()) return;
		Identifier id = this.getId();
		String scen_file = id.getFileName();
		String proj_name = id.getProjectName();

		// If this link is from a project that hasn't been loaded, do this!
		if (c.isFileLoaded(id.getFileName())) {
			c.setFileName(scen_file);
			// Load the project from XML dynamically
			try {
				ProjectType ptype = (new XMLInterface()).loadXMLFile(scen_file);
				(new GraphBuilder()).buildGraph(ptype, c);
			} catch (JAXBException exc) {
				System.out.println("[ERROR] [LinkSymbol.resolve] " + id.toString() + " referencing unknown file!");
				System.exit(-1);			
			}
		}
		
		
		try {
			Project p = c.getProject(proj_name);
			if (p == null) {
				System.out.println("[ERROR] [LinkSymbol.resolve] " + id.toString() + " referencing unloaded project!");
				System.exit(-1);
			}
			Scenario scen = p.getScenario(id.getScenarioName());
			// NASTY ASSUMPTION:  The structure of the information in the S-PMIF link nodes
			//  implies that there is only one graph (task) per scenario, whereas
			//  the data structure implies that there can be more than one!
			// We are checking this invariant at some point
			Collection<Graph> tasks = scen.getAllTasks();
			if (tasks.size() != 1) {
				System.out.println("[ERROR] [LinkSymbol.resolve] " + id.toString() + " has ambiguous graph reference!");
				System.exit(-1);				
			}
			Graph t = tasks.iterator().next();
			Node n = t.getNode(id.getNodeId());
			_node = n;
		} catch (AnalysisException exc) {
			System.out.println("[ERROR} [LinkSymbol.resolve] " + exc.getMessage());
			System.exit(-1);
		}
			
		return;		
	}
}
